package pl.shenlon.poker.cards;

import java.util.HashMap;
import java.util.Map;

public class Card implements Comparable<Card> {
	private static final Map<CardRank, String> ranks;
	private static final Map<CardSuit, String> suits;

	static {
		ranks = new HashMap<CardRank, String>();
		ranks.put(CardRank.ACE, "A");
		ranks.put(CardRank.TWO, "2");
		ranks.put(CardRank.THREE, "3");
		ranks.put(CardRank.FOUR, "4");
		ranks.put(CardRank.FIVE, "5");
		ranks.put(CardRank.SIX, "6");
		ranks.put(CardRank.SEVEN, "7");
		ranks.put(CardRank.EIGHT, "8");
		ranks.put(CardRank.NINE, "9");
		ranks.put(CardRank.TEN, "10");
		ranks.put(CardRank.JACK, "J");
		ranks.put(CardRank.QUEEN, "Q");
		ranks.put(CardRank.KING, "K");

		suits = new HashMap<CardSuit, String>();
		suits.put(CardSuit.SPADES, "\u2660");
		suits.put(CardSuit.CLUBS, "\u2663");
		suits.put(CardSuit.HEARTS, "\u2665");
		suits.put(CardSuit.DIAMONDS, "\u2666");
	}

	private boolean faceUp;
	private final CardRank rank;

	private final CardSuit suit;

	public Card(CardSuit suit, CardRank rank) {
		this.suit = suit;
		this.rank = rank;
	}

	public Card(String card) {
		String cardRank = null, cardSuit = null;
		if (card.length() == 2) {
			cardRank = card.substring(0, 1);
			cardSuit = card.substring(1);
		} else if (card.length() == 3) {
			cardRank = card.substring(0, 2);
			cardSuit = card.substring(2);
		} else {
			throw new IllegalArgumentException();
		}

		this.rank = getCardRankForString(cardRank);
		this.suit = getCardSuitForString(cardSuit);
	}

	@Override
	public int compareTo(Card card) {
		return Integer.compare(this.rank.ordinal(), card.rank.ordinal());
	}

	public boolean equals(CardSuit suit, CardRank rank) {
		return (this.rank.equals(rank) && this.suit.equals(suit));
	}

	@Override
	public boolean equals(Object other) {
		if (other != null && other instanceof Card) {
			Card that = (Card) other;
			return (this.rank.equals(that.rank) && this.suit.equals(that.suit));
		}
		return false;
	}

	private CardRank getCardRankForString(String cardRank) {
		for (CardRank rank : ranks.keySet()) {
			if (ranks.get(rank).equals(cardRank)) {
				return rank;
			}
		}
		return null;
	}

	private CardSuit getCardSuitForString(String cardSuit) {
		for (CardSuit suit : suits.keySet()) {
			if (suits.get(suit).equals(cardSuit)) {
				return suit;
			}
		}
		return null;
	}

	public CardRank getRank() {
		return rank;
	}

	public CardSuit getSuit() {
		return suit;
	}

	@Override
	public int hashCode() {
		return suit.ordinal() * 20 + rank.ordinal() + 1;
	}

	public boolean isFaceUp() {
		return faceUp;
	}

	public void setFaceUp(boolean faceUp) {
		this.faceUp = faceUp;
	}

	@Override
	public String toString() {
		return ranks.get(rank) + suits.get(suit);
	}
}